package com.clp.protocol.modbus_tcp.mb_frame.mb_body.mb_data.req;

import com.clp.protocol.core.utils.ByteUtil;
import com.clp.protocol.modbus_tcp.definition.MbByteOrder;
import com.clp.protocol.modbus_tcp.mb_frame.mb_body.mb_data.ReqMbData;
import io.netty.buffer.ByteBuf;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.nio.ByteOrder;
import java.util.List;
import java.util.Objects;

@Getter
@NoArgsConstructor
public class ForceMultiRegsReqMbData implements ReqMbData {
    /**
     * 起始地址
     */
    private int startAddr;
    /**
     * 数量
     */
    private int num;
    /**
     * 字节计数
     */
    private int byteCount;
    /**
     * 设置内容
     */
    private List<Integer> setVals;

    public ForceMultiRegsReqMbData(int startAddr, List<Integer> setVals) {
        this.startAddr = startAddr;
        this.num = setVals.size();
        this.byteCount = num * 2;
        this.setVals = setVals;
    }

    @Override
    public ReqMbData initBy(ByteBuf buf) {
        throw new UnsupportedOperationException();
    }

    @Override
    public boolean isValid() {
        if (startAddr < 0 || startAddr > 0xFFFF) return false;
        if (setVals == null) return false;
        if (num != setVals.size()) return false;
        return byteCount * 8 >= setVals.size();
    }

    @Override
    public void writeTo(ByteBuf buf) {
        // 起始地址
        buf.writeBytes(MbByteOrder.startAddrOrder == ByteOrder.BIG_ENDIAN ?
                ByteUtil.intToBytes2BE(startAddr) : ByteUtil.intToBytes2LE(startAddr));
        // 数量
        buf.writeBytes(MbByteOrder.numOrder == ByteOrder.BIG_ENDIAN ?
                ByteUtil.intToBytes2BE(num) : ByteUtil.intToBytes2LE(num));
        // 字节计数
        buf.writeByte(byteCount);
        // 设置内容
        for (Integer setVal : setVals) {
            buf.writeBytes(MbByteOrder.setRegOrder == ByteOrder.BIG_ENDIAN ?
                    buf.writeShort(setVal) : buf.writeShortLE(setVal));
        }
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("起始地址：" + startAddr + ", 数量：" + num + ", 字节计数：" + byteCount + ", 设置内容：");
        for (Integer setVal : setVals) {
            sb.append(" ").append(setVal);
        }
        return sb.toString();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        ForceMultiRegsReqMbData that = (ForceMultiRegsReqMbData) o;
        return startAddr == that.startAddr && num == that.num && byteCount == that.byteCount && Objects.equals(setVals, that.setVals);
    }

    @Override
    public int hashCode() {
        return Objects.hash(startAddr, num, byteCount, setVals);
    }
}
